// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Jeff Stewart
// Helper class to read information from the windows Registry.  It hides
// all the windowisms and adopts Qt's QString as the standard string
// representation.
#ifndef POPDIAG_CONFIG_REGISTRYKEY_H__
#define POPDIAG_CONFIG_REGISTRYKEY_H__

#include <QtCore/QTextStream>
#include <QtCore/QString>
#include <QtCore/QList>

#include "util/common.h"

namespace popdiag {

class RegistryKeyPrivate;

// expand windows-style %ENVIRONMENT% references:
QString ExpandEnvironmentReferences(const QString &in);

// A RegistryKey instance corresponds to a Key in the Windows
// Registry.  There are no public constructors.  Start with one of the
// static accessor methods (CurrentUser(), ClassesRoot(), or LocalMachine())
// to get a starting handle, and navigate from there using ChildKey().
class RegistryKey {
 public:
  virtual ~RegistryKey();

  // Get the HKCU.  You do not own the returned value.
  static const RegistryKey &CurrentUser();

  // Get the HKCR.  You do not own the returned value.
  static const RegistryKey &ClassesRoot();

  // Get the HKLM.  You do not own the returned value.
  static const RegistryKey &LocalMachine();

  // Populate out with the names of the immediate children of this node.
  // Returns true iff we were able to enumerate our children.
  // Note that even if this method returns true, out can still be empty.
  virtual bool GetChildKeyNames(QList<QString> *out) const = 0;

  // Retrieve a child key.  You can pass an immediate child name
  // or a backslash-delimited path to a child.  Returns non-null on
  // success.  You own the resulting key and must delete it.
  virtual RegistryKey *ChildKey(const QString &sub_key_name) const = 0;

  // Read a DWORD entry with name value_name.
  virtual bool ReadIntEntry(const QString &value_name, int *out) const = 0;

  // Read an SZ or EXPAND_SZ entry.
  virtual bool ReadStringEntry(const QString &value_name,
                               QString *out) const = 0;

  // reads a string stored in a REG_BINARY value.  If no such value is
  // found, looks for REG_SZ or REG_EXPANDSZ value by the same name.
  // This storage hack is used by OE6.  We need to read enough of them
  // to justify polluting this interface with a helper method.
  virtual bool ReadBinaryString(const QString &value_name,
                                QString *out) const = 0;

  // Read binary data from a registry value.  Returns NULL on error,
  // otherwise a data pointer to out_len_in_bytes data.  The return value
  // must be reclaimed by the caller by delete[]'ing it.
  virtual unsigned char *ReadBinaryEntry(const QString &value_name,
                                         size_t *out_len_in_bytes) const = 0;

  // Make a copy of the current key.
  // Caller must delete the result when done with it.
  virtual RegistryKey *Copy() const = 0;

  // Dump a diagnostic report of the contents of this key.  This is not
  // recursive.
  virtual QString Dump() const = 0;

  // Refresh the underlying content from storage.  While this guarantees
  // that you'll see any new values, you MAY see new values at any time.
  // This call may block.
  virtual void Refresh() = 0;
 protected:
  RegistryKey();
 private:
  DISALLOW_EVIL_CONSTRUCTORS(RegistryKey);
};
}  // namespace popdiag

#endif  // POPDIAG_CONFIG_REGISTRYKEY_H__
